package de.openkanban.server.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import de.openkanban.server.domain.User;
import de.openkanban.server.interceptor.annotation.SecurityInterception;
import de.openkanban.server.service.UserService;
import de.openkanban.server.session.OpenKanbanSessionAttributes;
import de.openkanban.server.util.MultipartUtil;
import de.openkanban.shared.dto.StatusDto;
import de.openkanban.shared.dto.UserDto;
import de.openkanban.shared.util.StatusCodes;

@Controller
@RequestMapping(value = "/user")
public class UserController {

	private static final String DEFAULT_AVATAR_PNG = "default.png";

	@Autowired
	private UserService userService;

	@Autowired
	private OpenKanbanSessionAttributes sessionAttributes;

	@Autowired
	private DozerBeanMapper mapper;

	@RequestMapping(method = RequestMethod.POST, value = "/signup")
	@ResponseBody
	public void createUser(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
		User user = MultipartUtil.processFiles(req, resp);
		userService.signUp(user);
	}

	@RequestMapping(method = RequestMethod.POST, value = "/login")
	@ResponseBody
	public UserDto loginUser(User user, HttpServletRequest req, HttpServletResponse resp) {
		// if login is valid then userId is set by the userService
		boolean logInSucessfull = userService.logIn(user);

		if (logInSucessfull) {
			req.getSession().setAttribute("userId", user.getUserId());

			user = userService.getUser(user.getUserId());
			UserDto userDto = mapper.map(user, UserDto.class);
			return userDto;
		} else {
			resp.setStatus(401);
			return null;
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/logout")
	@ResponseBody
	public String logoutUser(HttpServletRequest req, HttpServletResponse resp) {
		req.getSession().invalidate();
		return "success=true";
	}

	@RequestMapping(method = RequestMethod.POST, value = "/account")
	@ResponseBody
	@SecurityInterception
	public UserDto get(HttpServletRequest req, HttpServletResponse resp) {
		User user = userService.getUser(sessionAttributes.getUserId(req));
		return mapper.map(user, UserDto.class);
	}

	@RequestMapping(method = RequestMethod.GET, value = "/contact/get")
	@ResponseBody()
	@SecurityInterception
	public UserDto[] getContacts(HttpServletRequest req, HttpServletResponse resp) {
		User requestedUser = userService.getUser(sessionAttributes.getUserId(req));
		List<User> contactsArray = requestedUser.getKontakteEmailList();

		List<UserDto> userDtoList = new ArrayList<UserDto>();
		for (User user : contactsArray) {
			userDtoList.add(mapper.map(user, UserDto.class));
		}

		return userDtoList.toArray(new UserDto[] {});

	}

	@RequestMapping(method = RequestMethod.POST, value = "/contact/add")
	@ResponseBody
	@SecurityInterception
	public StatusDto addContact(String parentUserId, String contactMail, HttpServletRequest req, HttpServletResponse resp) {
		StatusCodes status = userService.addContact(parentUserId, contactMail);
		return new StatusDto(status.getStatusCode(), status.getStatusText());
	}

	@RequestMapping(method = RequestMethod.POST, value = "/contact/remove")
	@ResponseBody
	@SecurityInterception
	public StatusDto removeContact(String contactMail, HttpServletRequest req, HttpServletResponse resp) {
		User user = userService.getUser(sessionAttributes.getUserId(req));
		StatusCodes status = userService.removeContact(user, contactMail);
		return new StatusDto(status.getStatusCode(), status.getStatusText());
	}

	@RequestMapping(method = RequestMethod.POST, value = "/update/account")
	@ResponseBody
	@SecurityInterception
	public StatusDto updateAccount(UserDto userDto, HttpServletRequest req, HttpServletResponse resp) {
		User user = mapper.map(userDto, User.class);
		user.setUserId(sessionAttributes.getUserId(req));
		StatusCodes status = userService.updateUser(user);
		return new StatusDto(status.getStatusCode(), status.getStatusText());
	}

	@RequestMapping(method = RequestMethod.POST, value = "/update/password")
	@ResponseBody
	@SecurityInterception
	public StatusDto updatePassword(String oldPassword, String newPassword, HttpServletRequest req, HttpServletResponse resp) {
		StatusCodes status = userService.updatePassword(sessionAttributes.getUserId(req), oldPassword, newPassword);
		return new StatusDto(status.getStatusCode(), status.getStatusText());
	}

	@RequestMapping(method = RequestMethod.POST, value = "/update/avatar")
	@ResponseBody
	@SecurityInterception
	public StatusDto updateAvatar(HttpServletRequest req, HttpServletResponse resp) {
		User user = userService.getUser(sessionAttributes.getUserId(req));
		if (avatarDoesNotExist(user)) {
			User multipartUser = MultipartUtil.processFiles(req, resp);
			userService.updateAvatar(sessionAttributes.getUserId(req), multipartUser.getAvatarUrl());
		} else {
			MultipartUtil.processFiles(user.getAvatarUrl().replaceAll("\\..*", ""), req, resp);
		}
		return new StatusDto(StatusCodes.OK.getStatusCode(), StatusCodes.OK.getStatusText());
	}

	private boolean avatarDoesNotExist(User user) {
		return DEFAULT_AVATAR_PNG.equals(user.getAvatarUrl()) || StringUtils.isEmpty(user.getAvatarUrl());
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public void setSessionAttributes(OpenKanbanSessionAttributes sessionAttributes) {
		this.sessionAttributes = sessionAttributes;
	}

	public void setMapper(DozerBeanMapper mapper) {
		this.mapper = mapper;
	}

}
